package com.xiaolun.safe;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 线程不安全
 * 1、故障现象
 * 并发修改异常
 * java.util.ConcurrentModificationException
 * 2、导致原因
 * ArrayList在迭代的时候如果同时对其进行修改就会
 * 抛出并发修改异常。都在争那一把锁。
 * 3、解决方法
 * 3.1 使用new Vector<>()可以解决数据一致性的问题，但是可以降低性能。
 * 3.2 Collections.synchronizedList(new ArrayList<>())
 * 3.3 new CopyOnWriteArrayList<>() (是java中自己的类)，可以保证数据一致性，
 *  *  * 又可以保证并发性
 * 4、优化建议（同样的错误不要犯第二次）
 */
public class NotSafeDemo01 {
	public static void main(String[] args) {
		//只有一个主线程，不会出现错误
//		List<String> list = new ArrayList<>();
//		list.add("a");
//		list.add("b");
//		list.add("c");
//		list.forEach(System.out::println);//消费型函数

//		List<String> list = new ArrayList<>();
		//方法1解决并发
//		List<String> list = new Vector<>();
		//方法2
//		List<String> list = Collections.synchronizedList(new ArrayList<>());
//		List<String> list = new CopyOnWriteArrayList<>();
//
//		/**
//		 * 正确输出：
//		 * [null, b2b42f4a, 2309e123]
//		 * [null, b2b42f4a, 2309e123]
//		 * [null, b2b42f4a, 2309e123]
//		 * 错误输出： 数据不一致
//		 */
//		for (int i = 1; i <= 10; i++) {
//			new Thread(() -> {
//				list.add(UUID.randomUUID().toString().substring(0, 8));
//				System.out.println(list);
//			}, String.valueOf(i)).start();
//		}

//		listNotSafe();

		/**
		 * 1、HashSet报错：java.util.ConcurrentModificationException
		 * 2、解决方案：new CopyOnWriteArraySet<>();
		 */
//		setNotsafe();
		/**
		 * 1、HashMap报错:java.util.ConcurrentModificationException
		 * 2、解决方案：new ConcurrentHashMap<>();
		 */
		mapNotSafe();

	}

	private static void mapNotSafe() {
		//		Map<String,String> map= new HashMap<>();
		Map<String,String> map= new ConcurrentHashMap<>();
		for (int i = 1; i <= 30; i++) {
			new Thread(() -> {
				map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 8));
				System.out.println(map);
			}, String.valueOf(i)).start();
		}
	}

	private static void setNotsafe() {
//		Set<String> set= new HashSet<>();
		Set<String> set= new CopyOnWriteArraySet<>();
		for (int i = 1; i <= 30; i++) {
			new Thread(() -> {
				set.add(UUID.randomUUID().toString().substring(0, 8));
				System.out.println(set);
			}, String.valueOf(i)).start();
		}
	}

	//抽取代码
	private static void listNotSafe() {
//		List<String> list = new ArrayList<>();
		List<String> list = new CopyOnWriteArrayList<>();
		for (int i = 1; i <= 10; i++) {
			new Thread(() -> {
				list.add(UUID.randomUUID().toString().substring(0, 8));
				System.out.println(list);
			}, String.valueOf(i)).start();
		}
	}
}
